/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.loja.model.service.factory;

import br.com.loja.model.dao.IDAO;
import br.com.loja.model.dao.MapDAO;
import br.com.loja.model.dao.factory.IDAOFactory;
import br.com.loja.model.service.exception.ServiceException;
import br.com.loja.util.PropertiesApp;
import java.util.List;
import java.util.Map;

/**
 *
 * @author David Luiz
 */
public class ServiceFactoryProducer {

    private static final String PROPERTY = "serviceFactory";
    private static final ThreadLocal<ServiceFactory> SERVICE_FACTORY = new ThreadLocal<>();
    private static ServiceFactoryProducer instance;

    private ServiceFactoryProducer() {
    }

    public static ServiceFactoryProducer getInstance() {

        if (instance != null) {
            return instance;
        }

        synchronized (ServiceFactoryProducer.class) {
            if (instance != null) {
                return instance;
            }

            return instance = new ServiceFactoryProducer();
        }

    }

    //Avaliar uso de ThreadLocal quando usado com outros Presenters funcionando juntos 
    public ServiceFactory createServiceFactory() throws ServiceException {

        ServiceFactory factoryInThread = SERVICE_FACTORY.get();

        if (factoryInThread != null) {
            return factoryInThread;
        }

        synchronized (ServiceFactoryProducer.class) {
            if (factoryInThread != null) {
                return factoryInThread;
            }
            return getServiceFactoryFromProperties();
        }

    }

    public <T> ServiceFactory createServiceFactory(final List<T> database) throws ServiceException {

        ServiceFactory factory = new ServiceFactory() {

            @Override
            protected IDAOFactory getDAOFactory() {
                return new IDAOFactory() {

                    @Override
                    public <T> IDAO<T> getEntityDAO(Class<T> clazz) {
                        return (IDAO<T>) new MapDAO<>(database);
                    }
                };
            }
        };

        return factory;

    }

    private ServiceFactory getServiceFactoryFromProperties() throws ServiceException {

        try {

            String factoryClass = PropertiesApp.getInstance().getPropertyValue(PROPERTY);

            ClassLoader loader = this.getClass().getClassLoader();
            Class<?> classFactory = loader.loadClass(factoryClass);

            ServiceFactory serviceFactory = (ServiceFactory) classFactory.newInstance();
            SERVICE_FACTORY.set(serviceFactory);

            return serviceFactory;

        } catch (ClassNotFoundException e) {
            //TODO: Implementar Log
            throw new ServiceException("Não foi possivel encontrar o objeto informado", e);
        } catch (InstantiationException | IllegalAccessException e) {
            //TODO: Implementar Log
            throw new ServiceException("Não foi possivel utilizar o serviço informado", e);
        }
    }

}
